#ifndef _DRV_NEUL_H
#define _DRV_NEUL_H

#pragma diag_suppress 1295

#include <Includes.h>

//#define NEUL_MAX_BUF_SIZE 1064
//#define NEUL_MAX_BUF_SIZE 400
#define LOS_DEV_UART_DUALBUF_SIZE /*1024*/(4*1024)
#define NEUL_MAX_BUF_SIZE 208

#define NEUL_MAX_SOCKETS 1 // the max udp socket links
#define NEUL_IP_LEN 16
#define NEUL_IPV6_LEN 46
#define NEUL_MANUFACT_LEN 20
#define NEUL_IMEI_LEN    16
#define NEUL_IMSI_LEN    16
#define NEUL_NCCID_LEN   21
#define APN_NAME_LEN     128
#define NEUL_VER_LEN	 256

#define URC_FILTER(inBuffer,inLen,str,startMsg,endMsg) do{ \
	char *str1 = NULL, *p = NULL; \
	int len = 0, len1 = 0, len2 = 0, len3 = 0; \
	char tmpbuf[NEUL_MAX_BUF_SIZE] = {0}; \
	/*printf("URC_FILTER len %d %s",inLen, inBuffer);*/ \
	if(strstr(str,startMsg)==NULL) \
        break; \
	p = str+strlen(startMsg); \
	str1 = strstr(p, endMsg); \
	/*printf("startMsg %s, endMsg %s p %s",startMsg,endMsg,p);*/ \
	/*printf("0 str:%p inBuffer:%p p:%p str1:%p\r\n", str, inBuffer,p, str1);*/ \
	if(str1){ \
		p = str1+strlen(endMsg); \
		/*only urc msg*/ \
		if((str == inBuffer) && (p == (inBuffer + inLen))){ \
			/*printf("1\r\n");*/ \
			memset(inBuffer,0,inLen); \
			inLen = 0; \
		} \
		/*urc msg at head*/ \
		else if((str == inBuffer) && (p < (inBuffer + inLen))){ \
			len1 = (int)(p - str); \
			len = inLen - len1; \
			/*printf("2 inLen %d len1 %d len %d\r\n", inLen, len1,len);*/ \
			memcpy(tmpbuf, p, len); \
			memset(inBuffer, 0, inLen); \
			memcpy(inBuffer, tmpbuf, len); \
			inLen = len; \
		} \
		/*urc msg at middle*/ \
		else if((str > inBuffer) && (p < (inBuffer + inLen))){ \
			len1 = (int)(str - inBuffer); \
			memcpy(tmpbuf, inBuffer, len1); \
			len = len1; \
			len2 = (int)(p-str); \
			len3 = inLen-len1-len2; \
			memcpy(tmpbuf + len, p, len3); \
			len += len3; \
			/*printf("3 len1 %d len2 %d len3 %d len %d\r\n",len1,len2,len3,len);*/ \
			memset(inBuffer,0,inLen); \
			memcpy(inBuffer, tmpbuf, len); \
			inLen = len; \
		} \
		/*urc msg at tail*/ \
		else if((str > inBuffer) && (p == (inBuffer + inLen))){ \
			len = (int)(str - inBuffer); \
			/*printf("4 inLen %d len %d\r\n", inLen,len);*/ \
			memcpy(tmpbuf, inBuffer, len); \
			memset(inBuffer, 0, inLen); \
			memcpy(inBuffer, tmpbuf, len); \
			inLen = len; \
		}else{ \
			/*printf("5\r\n");*/ \
		} \
	}else{ \
		/*cannot find endmsg*/	\
		memset(inBuffer, 0, inLen);	\
		inLen = 0;	\
	} \
}while(0)

//内部宏,带重试次数执行命令
#define CMD_START(func,n,ret) {\
    int m=n;\
    while((ret = func) < 0){\
        if(m-- == 0){\
            return ret;\
        }\

#define CMD_END() \
            NeulBc28Sleep(30);\
        }\
    }\

#pragma pack(1)

typedef enum
{
    EN_DEV_TYPE_EC600S=DEV_EC600S,
    EN_DEV_TYPE_MAX
}EN_DEV_TYPE;


typedef enum{
	NOT_REG = 0,
	REG = 1,
	TRY_REG = 2,
	DENY_REG = 3,
	UNKNOW_REG = 4,
	ROAMING_REG = 5,
	INVALID_REG
}EN_REG_STATE;


typedef int (*neul_read)(char *buf, int maxrlen, int mode, unsigned int timeout);
typedef int (*neul_write)(char *buf, int writelen, int mode);
typedef int (*neul_state_chg)(void);
typedef int (*neul_time_set)(unsigned char year, unsigned char month, unsigned char day, unsigned char hour, unsigned char min, unsigned char second, unsigned char zone);

typedef struct _neul_dev_operation_t
{
    neul_read dev_read;
    neul_write dev_write;
	neul_state_chg state_chg;
	neul_state_chg iot_chg;
	neul_state_chg dev_chg;
	neul_time_set time_set;
} neul_dev_operation_t;

typedef struct _remote_info_t
{
    unsigned short port;
    int socket;
    char ip[16];
}remote_info;

typedef struct _neul_dev_info_t
{
	U8 imei[NEUL_IMEI_LEN];
	U8 imsi[NEUL_IMSI_LEN];
	U8 nccid[NEUL_NCCID_LEN];
	U8 pdpAddr0[NEUL_IPV6_LEN];
	U8 pdpAddr1[NEUL_IPV6_LEN];
    char *rbuf;
    char *wbuf;
    int remotecount;
    remote_info *addrinfo;
    neul_dev_operation_t *ops;
    char cdpip[16];
	char revision[NEUL_VER_LEN];
	/*U8 regStatus;*/ /*0 Not registered, UE is not currently searching an operator to register to##1 Registered, home network##2 Not registered, but UE is currently trying to attach or searching an operator to register to##3 Registration denied##4 Unknown (e.g. out of E-UTRAN coverage)##5 Registered, roaming*/
	/*U8 conStatus;*/ /*0 Idle, 1 Connected*/
} neul_dev_info_t;

typedef struct
{
	U8 imei[NEUL_IMEI_LEN];
	U8 imsi[NEUL_IMSI_LEN];
	U8 nccid[NEUL_NCCID_LEN];
	U8 pdpAddr0[NEUL_IPV6_LEN];
	U8 pdpAddr1[NEUL_IPV6_LEN];
	S32 rsrp;
	S32 totalPower;
	S32 txPower;
	U32 txTime;
	U32 rxTime;
	U32 cellId;
	U32 signalEcl;
	S32 snr;
	U32 earfcn;
	U32 signalPci;
	S32 rsrq;
	U8  opmode;
	/*U8 regStatus;*/ /*0 Not registered, UE is not currently searching an operator to register to##1 Registered, home network##2 Not registered, but UE is currently trying to attach or searching an operator to register to##3 Registration denied##4 Unknown (e.g. out of E-UTRAN coverage)##5 Registered, roaming*/
	/*U8 conStatus;*/ /*0 Idle, 1 Connected*/
}ST_NEUL_DEV;

#pragma pack()

int uart_data_read(char *buf, int maxrlen, int mode, int timeout);
int uart_data_write(char *buf, int writelen, int mode);
int NeulInit();
/**
@brief EC600S接收数据接口
@return 0成功，非0失败
**/
int Ec600sDataRead(char *buf, int maxrlen, int mode, unsigned int timeout);
/**
@brief EC600S接收数据处理,被EC600S任务调用
@return 0成功，非0失败
**/
void Ec600sRxDataProc();
/**
@brief convert char to hex string
@param bufin the data that need to convert
@param len data length
@param bufout hex string data
@return 0成功，非0失败
**/
int NeulBc28HexToStr(const unsigned char *bufin, int len, char *bufout);
/**
@brief convert hex string to hex data
@param bufin the data that need to convert
@param len data length
@param bufout hex data after convert
@return 0成功，非0失败
**/
int NeulBc28StrToHex(const char *bufin, int len, char *bufout);
/**
@brief 获取当前设备状态
@param
@return 设备状态
**/
int NeulDevStGet();

/**
@brief 获取当前设备是否就绪
@param
@return true就绪,flase未就绪
**/

bool NeulDevIsReady();

/**
@brief csq转换为rssi,gsm模式下由csq获取rssi,其他直接参考rsrp
@param csq 通过AT+CSQ获取的csq
@return rssi
**/
int Csq2Rssi(unsigned char csq);
/**
@brief LTE sinr转snr.Range: 0-250, which translates to -20dB - +30dB
@param sinr 通过AT+QENG获取的sinr
@return snr
**/
int Sinr2Snr(unsigned char sinr);

#endif

